#include <stdio.h>
#include "Unicode.h"
#include "Debug.h"

#define UTF8_COMPUTE(cChar, Mask, Len)				\
	if (cChar < 128)								\
		{ Len = 1;  Mask = 0x7f; }					\
	else if ((cChar & 0xe0) == 0xc0)				\
		{ Len = 2; Mask = 0x1f; }					\
	else if ((cChar & 0xf0) == 0xe0)				\
		{ Len = 3; Mask = 0x0f; }					\
	else if ((cChar & 0xf8) == 0xf0)				\
		{ Len = 4; Mask = 0x07; }					\
	else if ((cChar & 0xfc) == 0xf8)				\
		{ Len = 5; Mask = 0x03; }					\
	else if ((cChar & 0xfe) == 0xfc)				\
		{ Len = 6; Mask = 0x01; }					\
	else											\
		Len = -1;

#define UTF8_GET(Result, Chars, Count, Mask, Len)	\
	(Result) = (Chars)[0] & (Mask);					\
	for ((Count) = 1; (Count) < (Len); ++(Count))	\
	{												\
		if (((Chars)[(Count)] & 0xc0) != 0x80)		\
		{											\
			(Result) = -1;							\
			break;									\
		}											\
		(Result) <<= 6;								\
		(Result) |= ((Chars)[(Count)] & 0x3f);		\
	}

/*
Convert one set UTF-8 characters into the Unicode(UCS2) value.
arguments:
		utf8    pointer to the valid UTF-8 character.
		result  pointer to the location into which the UNICODE value of the
				UTF-8 character returns.
return:
		If the character is not valid, result holds -1.
		The function returns a pointer to the start of the next UTF-8 character.
		If utf8 is not well format, it will return NULL.
*/
char* _Utf8ConvUnicode(UInt16 *result, const char *utf8)
{
	Int32 unicode = *result;
	int i, mask = 0, len;

	UInt8 c = (UInt8) *utf8;

	if (!c)
		return 0;

	UTF8_COMPUTE (c, mask, len);

	if (len == -1)
		return 0;

	UTF8_GET (unicode, utf8, i, mask, len);

	if (unicode == -1)
		return 0;

	*result = (UInt16)unicode;

	return (char *) utf8 + len;
}

// Scan UTF-8 string and convert into szUnicode(UCS2) string
int ut_UTF8ToUnicode(UInt16 *szUnicode, const char *szUtf8, int iBufSize)
{
	char *str;
	int len;

	if( szUnicode == NULL || szUtf8 == NULL )
	{
		return -1;
	}

	str = (char *) szUtf8;

	len = 0;

	while( ( str = _Utf8ConvUnicode( szUnicode++, str) ) != 0 && len < iBufSize )
    {
		len++;
	}

	*(--szUnicode) = 0;

	return len;
}
